﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using VSIXUtilities.DataObjects;
using System.Collections.Specialized;
using System.Windows.Controls.Primitives;
using System.Windows.Markup;

namespace VSIXUtilities.GUI
{
    public delegate void NotifyItemsChangedEventHandler<T>(ToggleButtonTreeViewItem<T> item, object sender, NotifyCollectionChangedEventArgs e) where T : ToggleButton;
    [DefaultProperty("Text")]
    public class ToggleButtonTreeViewItem<T> : TreeViewItem, IDisposable where T : ToggleButton
	{
		#region Fields
		[Category("Behavior")]
		public event RoutedEventHandler Checked;
		[Category("Behavior")]
		public event RoutedEventHandler Indeterminate;
		[Category("Behavior")]
		public event RoutedEventHandler Unchecked;
		StackPanel StackPanelInstance;
		TextBlock TextBlockCaption;
		TextBlock TextBlockSpace;
		WeakEventListener WeakEventListenerInstance;
		// Summary:
		//     Represents the method that handles the System.Collections.Specialized.INotifyCollectionChanged.CollectionChanged
		//     event.
		//
		// Parameters:
		//   sender:
		//     The object that raised the event.
		//
		//   e:
		//     Information about the event.
        public event NotifyItemsChangedEventHandler<T> ItemsChanged;
        public static readonly DependencyProperty ContentStringFormatProperty = DependencyProperty.Register("Text", typeof(string), typeof(ToggleButtonTreeViewItem<T>), new FrameworkPropertyMetadata(string.Empty));
        
		#endregion

		#region Constructors
		public ToggleButtonTreeViewItem() : base()
		{
			StackPanelInstance = new StackPanel();
			StackPanelInstance.Orientation = Orientation.Horizontal;
			TextBlockSpace = new TextBlock() { Text = " " };
			TextBlockCaption = new TextBlock();
			ToggleButtonInstance = Activator.CreateInstance<T>();
            ToggleButtonInstance.IsChecked = false;
            ToggleButtonInstance.Content = StackPanelInstance;
			ToggleButtonInstance.Checked += new RoutedEventHandler(ToggleButtonInstance_Checked);
			ToggleButtonInstance.Indeterminate += new RoutedEventHandler(ToggleButtonInstance_Indeterminate);
			ToggleButtonInstance.Unchecked += new RoutedEventHandler(ToggleButtonInstance_Unchecked);

			WeakEventListenerInstance = new DataObjects.WeakEventListener();
			WeakEventListenerInstance.CollectionChangedEvent += new NotifyCollectionChangedEventHandler(Items_Changed);
			CollectionChangedEventManager.AddListener(Items, WeakEventListenerInstance);

			Header = ToggleButtonInstance;

			StackPanelInstance.Children.Add(new Image());
			StackPanelInstance.Children.Add(new Image() { Visibility = System.Windows.Visibility.Collapsed });
			StackPanelInstance.Children.Add(TextBlockSpace);
			StackPanelInstance.Children.Add(TextBlockCaption);
		}
		public ToggleButtonTreeViewItem(string Text, bool? IsChecked) : this()
		{
			this.Text = Text;
			this.IsChecked = IsChecked;
		}
		public ToggleButtonTreeViewItem(string Text, bool? IsChecked, Image CollapsedStateImage) : this(Text, IsChecked)
		{
            if (CollapsedStateImage != null)
            {
                this.CollapsedStateImage = CollapsedStateImage;
                this.CollapsedStateImage.Stretch = ImagesStretch;
            }
		}
		public ToggleButtonTreeViewItem(string Text, bool? IsChecked, Image CollapsedStateImage, Image ExpandedStateImage) : this(Text, IsChecked, CollapsedStateImage)
		{
            if (ExpandedStateImage != null)
            {
                this.ExpandedStateImage = ExpandedStateImage;
                this.ExpandedStateImage.Stretch = ImagesStretch;
            }
		}
		public ToggleButtonTreeViewItem(string Text, bool? IsChecked, System.Drawing.Image CollapsedStateImage) : this(Text, IsChecked, WFormsImageToWPFImage(CollapsedStateImage))
		{
		}
		public ToggleButtonTreeViewItem(string Text, bool? IsChecked, System.Drawing.Image CollapsedStateImage, System.Drawing.Image ExpandedStateImage) : this(Text, IsChecked, WFormsImageToWPFImage(CollapsedStateImage), WFormsImageToWPFImage(ExpandedStateImage))
		{
		}
		#endregion

		#region Helper Functions
		/// <summary>
		/// Convert a Fuckin old School System.Drawing.Image in a Beautiful
		/// new System.Windows.Controls.Image ;)
		/// </summary>
		/// <param name="Old_School_Image"></param>
		/// <returns></returns>
		private static System.Windows.Controls.Image WFormsImageToWPFImage(System.Drawing.Image Old_School_Image)
		{
			MemoryStream ms = new MemoryStream();
			Old_School_Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

			System.Windows.Media.Imaging.BitmapImage bImg = new System.Windows.Media.Imaging.BitmapImage();
			bImg.BeginInit();
			bImg.StreamSource = new MemoryStream(ms.ToArray());
			bImg.EndInit();

			System.Windows.Controls.Image WPFImage = new System.Windows.Controls.Image();
			WPFImage.Source = bImg;
			ms.Dispose();
			return WPFImage;
		}
		private static System.Drawing.Image WFormsImageFromWPFImage(System.Windows.Controls.Image Modern_School_Image)
		{
			return System.Drawing.Image.FromStream(((System.Windows.Media.Imaging.BitmapImage)Modern_School_Image.Source).StreamSource);
		}

		#endregion

		#region Events' Handlers
		void ToggleButtonInstance_Checked(object sender, RoutedEventArgs e)
		{
			if(!IsBeingUpdated && Checked != null)
			{
				Checked(this, e);
			}
		}
		void ToggleButtonInstance_Indeterminate(object sender, RoutedEventArgs e)
		{
			if(!IsBeingUpdated && Indeterminate != null)
			{
				Indeterminate(this, e);
			}
		}
		void ToggleButtonInstance_Unchecked(object sender, RoutedEventArgs e)
		{
			if(!IsBeingUpdated && Unchecked != null)
			{
				Unchecked(this, e);
			}
		}
		void Items_Changed(object sender, NotifyCollectionChangedEventArgs e)
		{
			if(!IsBeingUpdated && ItemsChanged != null)
			{
				ItemsChanged(this, Items, e);
			}
		}
		#endregion

		#region Public Functions
	
		public void BeginUpdate()
		{
			IsBeingUpdated = true;
		}
		public void EndUpdate()
		{
			IsBeingUpdated = false;
		}

		#endregion

		#region Properties

        public T ToggleButtonInstance
        {
            get;
            private set;
        }
		public Image CollapsedStateImage
		{
			get
			{
				return (Image)StackPanelInstance.Children[0];
			}
			set
			{
				StackPanelInstance.Children.RemoveAt(0);
				if(IsExpanded)
				{
					value.Visibility = System.Windows.Visibility.Collapsed;
				}
				else
				{
					value.Visibility = System.Windows.Visibility.Visible;
				}
				StackPanelInstance.Children.Insert(0, value);
			}
		}
		public System.Drawing.Image CollapsedStateImageEx
		{
			get
			{
				return WFormsImageFromWPFImage(CollapsedStateImage);
			}
		}
		public Image ExpandedStateImage
		{
			get
			{
				return (Image)StackPanelInstance.Children[1];
			}
			set
			{
				StackPanelInstance.Children.RemoveAt(1);
				if(IsExpanded)
				{
					value.Visibility = System.Windows.Visibility.Visible;
				}
				else
				{
					value.Visibility = System.Windows.Visibility.Collapsed;
				}
				StackPanelInstance.Children.Insert(1, value);
			}
		}
		public System.Drawing.Image ExpandedStateImageEx
		{
			get
			{
				return WFormsImageFromWPFImage(ExpandedStateImage);
			}
		}
		public Stretch ImagesStretch
		{
			get;
			set;
		}
		public bool IsBeingUpdated
		{
			get;
			private set;
		}
		public bool? IsChecked
		{
			get
			{
				return ToggleButtonInstance.IsChecked;
			}
			set
			{
				if(ToggleButtonInstance.IsChecked != value)
				{
					ToggleButtonInstance.IsChecked = value;
				}
			}
		}
		public double PreferedHeight
		{
			get
			{
				return StackPanelInstance.Height;
			}
			set
			{
				StackPanelInstance.Height = value;
			}
		}
        [Bindable(true)]
        public string Text
		{
			get
			{
				return TextBlockCaption.Text;
			}
			set
			{
				TextBlockCaption.Text = value;
			}
		}
		public List<ToggleButtonTreeViewItem<T>> ChildItems
		{
			get
			{
                List<ToggleButtonTreeViewItem<T>> Result = new List<ToggleButtonTreeViewItem<T>>();
				foreach(object objectItem in Items)
				{
                    Result.Add((ToggleButtonTreeViewItem<T>)objectItem);
				}
				return Result;
			}
		}
		
		#endregion
		
		#region Overriden Members

		protected override void OnCollapsed(RoutedEventArgs e)
		{
			base.OnCollapsed(e);
			if(CollapsedStateImage != null)
			{
				CollapsedStateImage.Visibility = System.Windows.Visibility.Visible;
			}
			if(ExpandedStateImage != null)
			{
				ExpandedStateImage.Visibility = System.Windows.Visibility.Collapsed;
			}
		}
		protected override void OnExpanded(RoutedEventArgs e)
		{
			base.OnExpanded(e);
			if(CollapsedStateImage != null)
			{
				CollapsedStateImage.Visibility = System.Windows.Visibility.Collapsed;
			}
			if(ExpandedStateImage != null)
			{
				ExpandedStateImage.Visibility = System.Windows.Visibility.Visible;
			}
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
			WeakEventListenerInstance.CollectionChangedEvent -= new NotifyCollectionChangedEventHandler(Items_Changed);
			CollectionChangedEventManager.RemoveListener(Items, WeakEventListenerInstance);
		}

		#endregion
	}
}
